package com.xiaohai.wx.weather.dao;



import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.log4j.Logger;
import org.joda.time.LocalDate;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.stereotype.Repository;
import com.xiaohai.wx.weather.dao.WeatherDao;
import com.xiaohai.wx.weather.dto.Weather;
import com.xiaohai.wx.weather.service.Constants;
import com.xiaohai.wx.weather.util.DateUtil;
import com.xiaohai.wx.weather.util.MessageUtil;
import com.xiaohai.wx.weather.util.NetworkUtil;
import com.xiaohai.wx.weather.util.PropertiesUtil;

@Repository("WeatherDao")
public class WeatherDao {
	
	final private String sinaUrl = "http://php.weather.sina.com.cn/xml.php?city=CITY&password=DJOYnieT8234jlsK&day=DAYNO";
	final private String pm25InUrl = "http://www.pm25.in/api/querys/pm2_5.json?city=CITY&token=TOKEN&stations=no";
	
	private static Map<String, CityCacheData> weatherMap = new HashMap<String, CityCacheData>();
	private static Map<String, Weather> yesterdayWeatherMap = new HashMap<String, Weather>();
	
	private Logger logger = Logger.getLogger(this.getClass());
	
	public List<Weather> getWeather(String cityName){

		CityCacheData data = weatherMap.get(cityName);
		
		if(data == null || data.isExpired()){
			refreshWeatherInCache(cityName);
			data = weatherMap.get(cityName);			
		}
		
		if(data == null){
			return null;
		}
		
		return (List<Weather>)data.getItemList();	
	}
	
	//this method will be invoked every night
	public static void clearAll(){
		yesterdayWeatherMap.clear();
		
		for(Map.Entry<String, CityCacheData> entry: weatherMap.entrySet()){
			String city = entry.getKey();
			Weather weather = entry.getValue().getItemList().get(0);
			yesterdayWeatherMap.put(city, weather);
		}
		
		weatherMap.clear();
	}
	
	private boolean refreshWeatherInCache(String cityName){
		
		logger.debug("begin to refresh weather in cache");
		
		CityCacheData data = this.getDataFromSina(cityName);
		
		//logger.debug(weatherList);
		if(data == null || data.getItemList().isEmpty()){
			return false;
		}else{
			
			List<String> aqiList = this.getAQIFromPM25In(cityName);
			if(aqiList != null){
				data.getItemList().get(0).setAqi_Index(aqiList.get(0));
				data.getItemList().get(0).setAir_quality(aqiList.get(1));
			}
			
			Weather yesterdayWeather = yesterdayWeatherMap.get(cityName);
			if( yesterdayWeather != null){
				String tempChange = getTempChange(data.getItemList().get(0), yesterdayWeather);
				data.getItemList().get(0).setTempChange(tempChange);
			}
			
			if(data.getItemList().get(1) !=null){
				String tempChange = getTempChange(data.getItemList().get(1), data.getItemList().get(0));
				data.getItemList().get(1).setTempChange(tempChange);
			}
			
			weatherMap.put(cityName, data);
			//logger.debug(weatherMap);
			return true;
		}
	}
	
	private String getTempChange(Weather todayTemp, Weather yesterdayTemp){
		
		String todayHighStr = todayTemp.getHighTemp();
		int todayHigh = Integer.parseInt(todayHighStr);
		String todayLowStr = todayTemp.getLowTemp();
		int todayLow = Integer.parseInt(todayLowStr);
		
		String yesterdayHighStr = yesterdayTemp.getHighTemp();
		int yesterdayHigh = Integer.parseInt(yesterdayHighStr);
		String yesterdayLowStr = yesterdayTemp.getLowTemp();
		int yesterdayLow = Integer.parseInt(yesterdayLowStr);
		
		//logger.debug("todayHigh: "+ todayHigh + "  todayLow: "+ todayLow + "  yesterdayHigh: "+ yesterdayHigh + " yesterdayLow: "+ yesterdayLow);
		
		String tempChange = "";
		
		if(todayHigh-yesterdayHigh >= 4 || todayLow - yesterdayLow >=4){
			tempChange = Constants.highTempNote;
		}
		
		if(yesterdayLow-todayLow >= 4 || yesterdayHigh - todayHigh >=4){
			tempChange = Constants.lowTempNote;
		}
		
		return tempChange;
		
	}
	
	@Deprecated
	private String getTempChange(String todayTemp, String yesterdayTemp){
		
		String todayHighStr = todayTemp.substring(0, todayTemp.indexOf("℃"));
		int todayHigh = Integer.parseInt(todayHighStr);
		String todayLowStr = todayTemp.substring(todayTemp.indexOf("~")+1, todayTemp.lastIndexOf("℃"));
		int todayLow = Integer.parseInt(todayLowStr);
		
		String yesterdayHighStr = yesterdayTemp.substring(0, yesterdayTemp.indexOf("℃"));
		int yesterdayHigh = Integer.parseInt(yesterdayHighStr);
		String yesterdayLowStr = yesterdayTemp.substring(yesterdayTemp.indexOf("~")+1, yesterdayTemp.lastIndexOf("℃"));
		int yesterdayLow = Integer.parseInt(yesterdayLowStr);
		
		logger.debug("todayHigh: "+ todayHigh + "  todayLow: "+ todayLow + "  yesterdayHigh: "+ yesterdayHigh + " yesterdayLow: "+ yesterdayLow);
		
		String tempChange = "";
		
		if(todayHigh-yesterdayHigh >= 4){
			tempChange = "大幅升温";
		}
		
		if(yesterdayLow-todayLow >= 4){
			tempChange = "气温骤降";
		}
		
		return tempChange;
		
	}
	
	public void testTempChange(){
		String todayTemp = "20℃~-3℃";
		String yesterdayTemp = "15℃~0℃";
		
		System.out.println(getTempChange(todayTemp, yesterdayTemp));
	}
	
	private CityCacheData getDataFromSina(String cityName){
		
		CityCacheData data = new CityCacheData();
		List<Weather> weatherList = new ArrayList<Weather>();
		try {
			cityName = URLEncoder.encode(cityName, "GB2312");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		String url = sinaUrl.replace("CITY", cityName);
		for (int i = 0; i< 5 ; i++){
			String url2 = url.replace("DAYNO", Integer.toString(i));
			
			Weather weather = MessageUtil.getWeatherFromXmlUrl(url2);
			if(weather != null){
				weatherList.add(weather);
			}else{
				break;
			}
		}
		
		if(weatherList.isEmpty()){
			return null;
		}else{
			data.setDataList(weatherList);
			data.setLastUpdatedTime(new Date());
			return data;
		}
	}

	@SuppressWarnings("unused")
	@Deprecated
	private CityCacheData get6DaysWeatherFromInternet(String cityCode) {
		
		String chinaWeatherUrl = "http://m.weather.com.cn/data/cityCode.html";
		CityCacheData cityData = new CityCacheData();
		
		String url = chinaWeatherUrl.replace("cityCode",cityCode);
		String JsonStr = NetworkUtil.readURLContent(url);
		//logger.debug("JsonStr got from china weather: "+ JsonStr);
		if(JsonStr == null){
			return null;
		}
		
		JSONParser parser = new JSONParser();
		List<Weather> weatherList = new ArrayList<Weather> ();
		try {
	 
			//Object obj = parser.parse(new FileReader("d:\\test.json"));
	 
			JSONObject jsonObject = (JSONObject) parser.parse(JsonStr);
	 
			JSONObject weatherObj = (JSONObject) jsonObject.get("weatherinfo");
			
			String pubDate = (String) weatherObj.get("date_y");
		
			Date date = new Date();
			try {
				date = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA).parse(pubDate);
				if(DateUtil.is3DaysOld(date)){
					return null;
				}
			} catch (java.text.ParseException e) {
				logger.error("Can't parse weather JSON date string: ", e);
			}
			
			LocalDate pubDay = new LocalDate(date);
			LocalDate today = new LocalDate();
			
			for(int i =0; i<6; i++){
				LocalDate theDay = pubDay.plusDays(i);
				if(theDay.isBefore(today)){
					continue;
				}
				
				int j = i+1;
				
				if(weatherObj.get("temp"+j) != null){
					Weather weather = new Weather();
					
					//weather.setTemp((String) weatherObj.get("temp"+j));
					weather.setWeather((String) weatherObj.get("weather"+j));
					weather.setWind((String) weatherObj.get("wind"+j));
					weather.setDate(theDay);
					
					weatherList.add(weather);
				}
			}
			
			cityData.setDataList(weatherList);
			
			if(pubDay.isEqual(today)){
				weatherList.get(0).setIndex_dress((String) weatherObj.get("index_d"));
				weatherList.get(0).setIndex_uv((String) weatherObj.get("index_uv"));
				cityData.setLastUpdatedTime(new Date());
			}else{
				weatherList.get(0).setIndex_dress((String) weatherObj.get("index48_d"));
				weatherList.get(0).setIndex_uv((String) weatherObj.get("index48_uv"));
				cityData.setLastUpdatedTime(date);
			}
			
			
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
		return cityData;
	}
	
	private List<String> getAQIFromPM25In(String cityName){
		
		String token = "5j1znBVAsnSf5xQyNQyq";
		try {
			token = PropertiesUtil.getProperty("pm25InAppKey");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		String url = pm25InUrl.replace("TOKEN", token);
		url = url.replace("CITY", cityName);
		
		//logger.debug(url);
		
		String JsonStr = NetworkUtil.readURLContent(url);
		
		if(JsonStr == null || JsonStr.contains("error")){
			return null;
		}
		
		JsonStr = JsonStr.substring(1, JsonStr.length()-1);
		
		JSONParser parser = new JSONParser();
		
		System.out.println(JsonStr);
		
		try {
			JSONObject jsonObject = (JSONObject) parser.parse(JsonStr);
			//Long pm2_5 = (Long) jsonObject.get("pm2_5");
			Long aqi = (Long) jsonObject.get("aqi");
			String quality = (String) jsonObject.get("quality");
			
			
			List<String> resultList = new ArrayList<String> ();
			resultList.add(aqi.toString());
			resultList.add(quality);
			return resultList;
			
		} catch (ParseException e) {			
			e.printStackTrace();
			return null;
		}
	}
	
	public void testPM25Connect(){
		
		String[] cities = {"北京","上海","重庆"};
		for(String city : cities){
			System.out.println(city);
			List<String> result = this.getAQIFromPM25In(city);
			System.out.println(result);
		}
	}
	
	public void testGetAll(String cityName){
		List<Weather> weatherList = this.getWeather(cityName);
		System.out.println(MessageUtil.get3DayWeatherStr(weatherList, cityName));
	}
	
	
	public static void main(String[] args){
		
		WeatherDao dao = new WeatherDao();
		
		//dao.testPM25Connect();
		
		dao.testGetAll("北京");
	
		
	}

}
